home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Software Contest 3
/
FM Towns Software Contest 3.iso
/
exp
/
bpp
/
no1
/
bpp.bas
next >
Wrap
BASIC Source File
|
1994-01-07
|
25KB
|
907 lines
10 ' *****************************************
20 ' *** ***
30 ' *** BPP - BASIC PreProcessor ***
40 ' *** ***
50 ' *** Copyright (c) 1992 Fuko-CMC ***
60 ' *** Programmed by TmSof ***
70 ' *** ***
80 ' *****************************************
90 '
100 ' $FILE 13
110 '
120 DEFINT A-Z
130 VERSION$="Version 0.90" ' *** Version number here! ***
140 DEF FNITOA$(I%)=MID$(STR$(I),2+(I%<0))
150 CDPLAYFLAG=0 ' *** CD auto playing 0.NO 1.YES ***
160 '
170 ' *** Grobal Defines ***
180 '
190 SEPARATOR$=" ,:!#$%()=-^\+*;<>?_/'"
200 '
210 ' *** Macro Define Symbol Table ***
220 '
230 MAXMACRO=255:MAXMACROPARAM=15:NUMOFMACDEF=0
240 DIM MACID$(MAXMACRO) ' macro identifer
250 DIM MACRP$(MAXMACRO) ' replace strings
260 DIM MACPC (MAXMACRO) ' number of param.
270 DIM MACPA$(MAXMACRO,MAXMACROPARAM) ' Each param.
280 DIM MACTEMP$(MAXMACROPARAM)
290 '
300 ' *** Other Variables for PASS 1 ***
310 '
320 MAXINCLUDENEST=15:INCLUDENEST=0
330 DIM LINECOUNTER (MAXINCLUDENEST)
340 '
350 ' *** Block Structure Management Table ***
360 '
370 MAXBLOCKNEST=31:BLOCKNEST=0
380 DIM BLKTYP$(MAXBLOCKNEST) ' block type
390 DIM BLKFLG$(MAXBLOCKNEST) ' flags of structuring
400 DIM BLKEXITL$(MAXBLOCKNEST) ' label id to exit the block
410 DIM BLKLOOPL$(MAXBLOCKNEST) ' label id to loop the block
420 '
430 ' *** Sub-routines Declarations Symbol Table ***
440 '
450 MAXSUB=127:NUMOFSUB=0:MAXSUBPARAM=31
460 DIM SUBID$(MAXSUB) ' identifer of sub-routine
470 DIM SUBPC(MAXSUB) ' count of parameters
480 DIM SUBPARA(MAXSUB,MAXSUBPARAM) ' parameter list
490 DIM SUBPTYP(MAXSUB,MAXSUBPARAM) ' type of each parameters
500 DIM PARA$(MAXSUBPARAM)
510 '
520 ' *** Local Label Control ***
530 '
540 MAXLLAB=511:NUMOFLLAB=0
550 NUMOFBLKLLBL=0
560 '
570 ' *** Local Variable Symbol Table ***
580 '
590 STACKSIZE=511
600 STACKPTR$="ZZZSPT%"
610 STACKID$="ZZZSTK"
620 MAXLVAR=63
630 DIM NUMOFLVAR(3) ' number of local variable
640 DIM LVARGID$(3,MAXLVAR) ' grobal name of locals
650 FOR I=0 TO 3:NUMOFLVAR(I)=0:NEXT
660 '
670 ' *** BPP main ***
680 '
690 *MAIN
700 IF CDPLAYFLAG THEN GOSUB *CDSTART
710 PRINT
720 PRINT "BPP -- BASIC PreProsessor -- ";VERSION$
730 PRINT "Copyright (c) 1992 Fuko-CMC / Programmed by TmSof^^;"
740 PRINT
750 '
760 PRINT "Source Filename [.bpp] : ";:LINE INPUT SOURCEFILE$
770 P=INSTR(SOURCEFILE$,".")
780 IF P>0 THEN 820
790 FILEBASE$=SOURCEFILE$
800 SOURCEFILE$=SOURCEFILE$+".bpp"
810 GOTO 830
820 FILEBASE$=LEFT$(SOURCEFILE$,P-1)
830 OUTFILE$=FILEBASE$+".p1"
840 GOSUB *PASS1
850 '
860 SOURCEFILE$=OUTFILE$
870 OUTFILE$=FILEBASE$+".p2"
880 GOSUB *PASS2
890 '
900 SOURCEFILE$=OUTFILE$
910 OUTFILE$=FILEBASE$+".bas"
920 GOSUB *PASS3
930 '
940 PRINT
950 PRINT "Complete!!!"
960 IF CDPLAYFLAG THEN GOSUB *CDBREAK
970 END
980 '
990 ' *** CD Auto Player ^^; ... OMAKE ***
1000 '
1010 *CDSTART
1020 ON ERROR GOTO 1100
1030 CD PLAY
1040 ON ERROR GOTO 0
1050 INTERVAL 5
1060 ON INTERVAL GOSUB *CDCHECK
1070 INTERVAL ON
1080 RETURN
1090 '
1100 RESUME 1110
1110 ON ERROR GOTO 0
1120 CDPLAYFLAG=0
1130 RETURN
1140 '
1150 *CDCHECK
1160 CDSTAT CDSTATUS
1170 IF CDSTATUS(1) THEN RETURN
1180 CD PLAY
1190 RETURN
1200 '
1210 *CDBREAK
1220 INTERVAL OFF
1230 CD STOP
1240 RETURN
1250 '
1260 ' *** KILL EXISTING FILE ***
1270 '
1280 *KILLFILE
1290 KILL OUTFILE$
1300 RESUME
1310 '
1320 ' *** PASS 1 : Pre-Preprcessing ***
1330 '
1340 *PASS1
1350 PRINT"PASS 1 --- Pre-Preprocessing"
1360 INCLUDENEST=0:LINECOUNTER(INCLUDENEST)=0
1370 LINES=0
1380 ON ERROR GOTO *KILLFILE
1390 OPEN OUTFILE$ FOR OUTPUT AS #1
1400 ON ERROR GOTO 0
1410 OPEN SOURCEFILE$ FOR INPUT AS #2
1420 PRINT#1,"' [ BPP PASS 1 ]"
1430 GOSUB *PREPRE
1440 CLOSE #1:CLOSE #2
1450 PRINT USING "##### lines done.";LINES
1460 RETURN
1470 '
1480 ' *** Get a line ***
1490 '
1500 LINECOUNTER(INCLUDENEST)=LINECOUNTER(INCLUDENEST)+1
1510 LINE INPUT#(INCLUDENEST+2),L$
1520 LINES=LINES+1
1530 PRINT USING "##### lines ..."+CHR$(13);LINES;
1540 RETURN
1550 '
1560 ' *** Body of Pre-Preprocessing
1570 '
1580 *PREPRE
1590 WHILE EOF(INCLUDENEST+2)=0
1600 GOSUB 1500
1610 GOSUB *TRIMLINE
1620 GOSUB *TOUPPER
1630 IF LEFT$(L$,1)="#" THEN GOSUB 1690 ELSE GOSUB 2120
1640 WEND
1650 RETURN
1660 '
1670 ' *** Pre-Presrocessor Command Jmp.Tbl. ***
1680 '
1690 PRINT#1,"'"+L$+" ";STRING$(INCLUDENEST+1,"#");
1700 PRINT#1,FNITOA$(LINECOUNTER(INCLUDENEST))
1710 GOSUB *GETTOKEN
1720 GOSUB *GETTOKEN
1730 IF TKN$="INCLUDE" THEN 1820
1740 IF TKN$="DEFINE" THEN 1960
1750 IF TKN$="IFDEF" THEN 2510
1760 IF TKN$="IFNDEF" THEN 2550
1770 IF TKN$="ENDIF" THEN 2840
1780 RETURN
1790 '
1800 ' *** INCLUDE ***
1810 '
1820 GOSUB *GETTOKEN
1830 IF TKN$="" THEN 1820
1840 'on error goto *****
1850 INCLUDENEST=INCLUDENEST+1
1860 LINECOUNTER(INCLUDENEST)=0
1870 OPEN TKN$ FOR INPUT AS #(INCLUDENEST+2)
1880 'on error goto 0
1890 GOSUB *PREPRE
1900 CLOSE #(INCLUDENEST+2)
1910 INCLUDENEST=INCLUDENEST-1
1920 RETURN
1930 '
1940 ' *** DEFINE ***
1950 '
1960 MNUM=NUMOFMACDEF
1970 GOSUB *GETTOKEN
1980 MACID$(MNUM)=TKN$
1990 IF SEP$<>"(" THEN MACPC(NMUM)=0:GOTO 2060
2000 PNUM=0
2010 GOSUB *GETTOKEN
2020 MACPA$(MNUM,PNUM)=TKN$
2030 IF SEP$<>")" THEN PNUM=PNUM+1:GOTO 2010
2040 MACPC(MNUM)=PNUM+1
2050 GOSUB *GETTOKEN
2060 MACRP$(MNUM)=L$
2070 NUMOFMACDEF=NUMOFMACDEF+1
2080 RETURN
2090 '
2100 ' *** Macro Replacing ***
2110 '
2120 GOSUB *GETTOKEN
2130 IF TKN$="" THEN 2450
2140 I=0
2150 WHILE I<NUMOFMACDEF
2160 IF TKN$<>MACID$(I) THEN 2430
2170 IF MACPC(I) THEN 2210
2180 PRINT#1,MACRP$(I);
2190 IF SEP$=CHR$(13) THEN PRINT#1,"" ELSE PRINT#1,SEP$;
2200 GOTO 2460
2210 PNUM=0
2220 MACTEMP$(PNUM)=""
2230 GOSUB *GETTOKEN
2240 MACTEMP$(PNUM)=MACTEMP$(PNUM)+TKN$
2250 IF SEP$=")" THEN 2290
2260 IF SEP$="," THEN PNUM=PNUM+1:GOTO 2220
2270 MACTEMP$(PNUM)=MACTEMP$(PNUM)+SEP$
2280 GOTO 2230
2290 PNUM=PNUM+1
2300 LBUF$=L$:TBUF$=TKN$:SBUF$=SEP$
2310 L$=MACRP$(I):R$=""
2320 GOSUB *GETTOKEN
2330 J=0
2340 WHILE J<MACPC(I)
2350 IF TKN$<>MACPA$(I,J) THEN 2370
2360 TKN$=MACTEMP$(J):GOTO 2390
2370 J=J+1
2380 WEND
2390 R$=R$+TKN$:IF SEP$<>CHR$(13) AND SEP$<>CHR$(34) THEN R$=R$+SEP$
2400 IF SEP$<>CHR$(13) THEN 2320
2410 L$=R$+LBUF$:TKN$=TBUF$:SEP$=SBUF$
2420 GOTO 2460
2430 I=I+1
2440 WEND
2450 GOSUB 2890
2460 IF SEP$<>CHR$(13) THEN 2120
2470 RETURN
2480 '
2490 ' *** IFDEF ***
2500 '
2510 COND=-1:GOTO 2590
2520 '
2530 ' *** IFNDEF ***
2540 '
2550 COND=0
2560 '
2570 ' *** Body of IFDEF/IFNDEF ***
2580 '
2590 GOSUB *GETTOKEN
2600 I=0:R=0
2610 WHILE I<NUMOFMACDEF
2620 IF TKN$=MACID$(I) THEN R=-1:GOTO 2660
2630 I=I+1
2640 WEND
2650 R=0
2660 IF R=COND THEN 2790
2670 ' [ else ]
2680 IFNEST=0
2690 GOSUB 1500
2700 GOSUB *TRIMLINE
2710 GOSUB *TOUPPER
2720 IF LEFT$(L$,3)="#IF" THEN IFNEST=IFNEST+1
2730 IF LEFT$(L$,6)<>"#ENDIF" THEN 2690
2740 IF IFNEST>0 THEN IFNEST=IFNEST-1:GOTO 2690
2750 PRINT#1,"'"+L$+" ";
2760 PRINT#1,STRING$(INCLUDENEST+1,"#");FNITOA$(LINECOUNTER(INCLUDENEST))
2770 RETURN
2780 ' [ then ]
2790 BLOCKNEST=BLOCKNEST+1
2800 RETURN
2810 '
2820 ' *** ENDIF ***
2830 '
2840 BLOCKNEST=BLOCKNEST-1
2850 RETURN
2860 '
2870 ' *** Output Token ***
2880 '
2890 IF SEP$=CHR$(34) THEN PRINT#1,TKN$;:RETURN
2900 IF SEP$<>CHR$(13) THEN PRINT#1,TKN$;SEP$;:RETURN
2910 LN$=FNITOA$(LINECOUNTER(INCLUDENEST))
2920 PRINT#1,TKN$+" '"+STRING$(INCLUDENEST+1,"#");
2930 PRINT#1,LN$
2940 RETURN
2950 '
2960 ' *** PASS 2 --- Block Structuring ***
2970 '
2980 *PASS2
2990 PRINT"PASS 2 --- Block Structuring"
3000 ON ERROR GOTO *KILLFILE
3010 OPEN OUTFILE$ FOR OUTPUT AS #1
3020 ON ERROR GOTO 0
3030 OPEN SOURCEFILE$ FOR INPUT AS #2
3040 BLOCKNEST=-1
3050 DEFAULTVARTYPE=0 'SNG
3060 INSUB=0:ELSEIF=0:LINES=0
3070 LM$="' [ BPP PASS 2 ]":LR$="":GOSUB 3170
3080 GOSUB *STRUC
3090 CLOSE #1:CLOSE #2
3100 PRINT USING "##### lines done.";LINES
3110 RETURN
3120 '
3130 ' *** Output a Line ***
3140 ' [input] LM$ : content of the line
3150 ' LR$ : comment of the line
3160 '
3170 PRINT#1,LM$;
3180 IF LR$<>"" THEN PRINT#1,"'"+LR$;
3190 PRINT#1,""
3200 LM$="":LR$=""
3210 RETURN
3220 '
3230 ' *** Get a Line ***
3240 '
3250 LINE INPUT #2,L$
3260 LINES=LINES+1
3270 PRINT USING "##### lines ..."+CHR$(13);LINES;
3280 QF=0
3290 FOR I=1 TO KLEN(L$)
3300 A$=KMID$(L$,I,1)
3310 IF A$=CHR$(34) THEN QF=1-QF
3320 IF A$="'" AND QF=0 THEN 3360
3330 NEXT
3340 RETURN
3350 '
3360 IF I<KLEN(L$) THEN LR$=KMID$(L$,I+1) ELSE LR$=""
3370 IF I>1 THEN L$=KMID$(L$,1,I-1) ELSE L$=""
3380 RETURN
3390 '
3400 ' *** Get a Token ***
3410 '
3420 GOSUB *GETTOKEN
3430 IF SEP$=CHR$(13) THEN EOL=-1 ELSE EOL=0
3440 IF SEP$=":" THEN SEP$=CHR$(13)
3450 RETURN
3460 '
3470 ' *** Build Structure ***
3480 '
3490 *STRUC
3500 WHILE EOF(2)=0
3510 IF L$="" THEN GOSUB 3250:GOSUB *TRIMLINE
3520 GOSUB 3420
3530 IF TKN$="SUB" THEN GOSUB 4020:GOTO 3760
3540 IF TKN$="ENDSUB" THEN GOSUB 4450:GOTO 3760
3550 IF TKN$="EXITSUB" THEN GOSUB 4590:GOTO 3760
3560 IF TKN$="FOR" THEN GOSUB 4700:GOTO 3760
3570 IF TKN$="NEXT" THEN GOSUB 5190:GOTO 3760
3580 IF TKN$="BREAK" THEN GOSUB 5500:GOTO 3760
3590 IF TKN$="IF" THEN GOSUB 5640:GOTO 3760
3600 IF TKN$="ENDIF" THEN GOSUB 5990:GOTO 3760
3610 IF TKN$="ELSEIF" THEN GOSUB 6080:GOTO 3760
3620 IF TKN$="WHILE" THEN GOSUB 6180:GOTO 3760
3630 IF TKN$="WEND" THEN GOSUB 6280:GOTO 3760
3640 IF TKN$="DO" THEN GOSUB 6360:GOTO 3760
3650 IF TKN$="LOOP" THEN GOSUB 6480:GOTO 3760
3660 IF TKN$="MAKESTACK" THEN GOSUB 6840:GOTO 3760
3670 IF TKN$="DEFSNG" THEN GOSUB 7100:GOTO 3760
3680 IF TKN$="DEFDBL" THEN GOSUB 7150:GOTO 3760
3690 IF TKN$="DEFSTR" THEN GOSUB 7200:GOTO 3760
3700 IF TKN$="DEFINT" THEN GOSUB 7250:GOTO 3760
3710 '
3720 IF TKN$="ELSE" THEN GOSUB 5850:GOTO 3760
3730 IF INSUB THEN GOSUB 3860
3740 LM$=LM$+TKN$
3750 IF SEP$=CHR$(34) THEN SEP$=""
3760 IF SEP$<>CHR$(13) THEN LM$=LM$+SEP$:GOSUB 3420:GOTO 3720
3770 GOSUB 3170
3780 IF EOL=0 THEN 3810
3790 IF BLOCKNEST<0 THEN 3810
3800 IF BLKTYP$(BLOCKNEST)="IF1" THEN GOSUB 5990:GOSUB 3170
3810 WEND
3820 RETURN
3830 '
3840 ' *** Solve Local Variable Relations ***
3850 '
3860 TYP=INSTR("!#$%",SEP$)-1
3870 IF TYP>=0 THEN S$=SEP$:T$=TKN$:GOSUB 3420:TKN$=T$
3880 IF TYP=-1 THEN TYP=DEFAULTVARTYPE:S$=""
3890 IF NUMOFLVAR(TYP)=0 THEN 3930
3900 FOR I=0 TO NUMOFLVAR(TYP)-1
3910 IF LVARGID$(TYP,I)=TKN$ THEN 3950
3920 NEXT
3930 SEP$=S$+SEP$
3940 RETURN
3950 TKN$=STACKID$+MID$("!#$%",TYP+1,1)
3960 TKN$=TKN$+"("+STACKPTR$+"("+FNITOA$(TYP)+")+"
3970 TKN$=TKN$+STK$+FNITOA$(I-NUMOFLVAR(TYP))+")"
3980 RETURN
3990 '
4000 ' *** SUB-routine Declaration ***
4010 '
4020 BLOCKNEST=BLOCKNEST+1
4030 FOR I=0 TO 3
4040 NUMOFLVAR(I)=0
4050 NEXT
4060 GOSUB 3420
4070 SUBID$(NUMOFSUB)=TKN$
4080 BLKEXITL$(BLOCKNEST)="ZZZ"+FNITOA$(NUMOFBLKLLBL)
4090 NUMOFBLKLLBL=NUMOFBLKLLBL+1
4100 LM$="*"+SUBID$(NUMOFSUB)
4110 IF SEP$="(" THEN GOSUB 4170 ELSE SUBPC(NUMOFSUB)=0
4120 GOSUB 6640:GOSUB 4350
4130 BLKTYP$(BLOCKNEST)="SUB"
4140 INSUB=1:SEP$=CHR$(13)
4150 RETURN
4160 ' [ get parameter list ]
4170 PNUM=0
4180 GOSUB 3420
4190 IF TKN$="" THEN 4310
4200 IF TKN$="BYBODY" THEN PBDY=1:GOSUB 3420 ELSE PBDY=0
4210 TYP=INSTR("!#$%",SEP$)-1
4220 IF TYP>=0 THEN T$=TKN$:GOSUB 3420:TKN$=T$
4230 IF TYP=-1 THEN TYP=DEFAULTVARTYPE
4240 GID$=TKN$
4250 LID=NUMOFLVAR(TYP)
4260 SUBPARA(NUMOFSUB,PNUM)=LID
4270 SUBPTYP(NUMOFSUB,PNUM)=TYP+PBDY*10
4280 LVARGID$(TYP,LID)=GID$
4290 NUMOFLVAR(TYP)=LID+1
4300 PNUM=PNUM+1
4310 IF SEP$<>")" GOTO 4180
4320 SUBPC(NUMOFSUB)=PNUM
4330 RETURN
4340 ' [ shift stack pointer ]
4350 FOR I=0 TO 3
4360 IF NUMOFLVAR(I)=0 THEN 4400
4370 GOSUB 3170
4380 SP$=STACKPTR$+"("+FNITOA$(I)+")"
4390 LM$=SP$+"="+SP$+"+"+FNITOA$(NUMOFLVAR(I))
4400 NEXT
4410 RETURN
4420 '
4430 ' *** End of SUB-routine Declaration ***
4440 '
4450 INSUB=0
4460 LM$="*"+BLKEXITL$(BLOCKNEST):GOSUB 3170
4470 FOR I=0 TO 3
4480 IF NUMOFLVAR(I)=0 THEN 4510
4490 SP$=STACKPTR$+"("+FNITOA$(I)+")"
4500 LM$=SP$+"="+SP$+"-"+FNITOA$(NUMOFLVAR(I)):GOSUB 3170
4510 NEXT
4520 LM$="RETURN":SEP$=CHR$(13)
4530 NUMOFSUB=NUMOFSUB+1
4540 BLOCKNEST=BLOCKNEST-1
4550 RETURN
4560 '
4570 ' *** EXITSUB ***
4580 '
4590 'if insub=0 then !error
4600 FOR I=BLKNEST TO 0 STEP -1
4610 IF BLKTYP$(I)="SUB" THEN 4640
4620 NEXT
4630 RETURN
4640 LM$="GOTO *"+BLKEXITL$(I)
4650 SEP$=CHR$(13)
4660 RETURN
4670 '
4680 ' *** FOR ***
4690 '
4700 T$=TKN$:S$=SEP$:LB$=""
4710 GOSUB 3420
4720 LB$=LB$+TKN$
4730 IF SEP$=CHR$(13) THEN 5090
4740 IF SEP$="," THEN 4780
4750 IF SEP$<>CHR$(34) THEN LB$=LB$+SEP$
4760 GOTO 4710
4770 ' [ FOR statment type 2 ]
4780 BLOCKNEST=BLOCKNEST+1
4790 LM$=LM$+LB$:GOSUB 3170
4800 LB$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
4810 LM$="*"+LB$:GOSUB 3170
4820 BLKLOOPL$(BLOCKNEST)=LB$
4830 NUMOFBLKLLBL=NUMOFBLKLLBL+1
4840 BLKTYP$(BLOCKNEST)="FOR"
4850 BNEST=0
4860 LB$=""
4870 GOSUB 3420
4880 LB$=LB$+TKN$
4890 IF SEP$="(" THEN BNEST=BNEST+1
4900 IF SEP$=")" THEN BNEST=BNEST-1
4910 IF SEP$="," AND BNEST=0 THEN 4940
4920 IF SEP$<>CHR$(34) THEN LB$=LB$+SEP$
4930 GOTO 4870
4940 EL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
4950 NUMOFBLKLLBL=NUMOFBLKLLBL+1
4960 LZ$="IF ("+LB$+")=0 THEN *"+EL$
4970 BLKEXITL$(BLOCKNEST)=EL$
4980 LB$=""
4990 GOSUB 3420
5000 LB$=LB$+TKN$
5010 IF SEP$=CHR$(13) THEN 5040
5020 IF SEP$<>CHR$(34) THEN LB$=LB$+SEP$
5030 GOTO 4990
5040 BLKFLG$(BLOCKNEST)=LB$
5050 TKN$="":SEP$=""
5060 IF L$="" THEN L$=LZ$ ELSE L$=LZ$+":"+L$
5070 RETURN
5080 ' [ FOR statment type 1 (STANDARD) ]
5090 BLOCKNEST=BLOCKNEST+1
5100 LZ$=T$+S$+LB$:TKN$="":SEP$=""
5110 IF L$="" THEN L$=LZ$ ELSE L$=LZ$+":"+L$
5120 BLKTYP$(BLOCKNEST)="FOR1"
5130 BLKEXITL$(BLOCKNEST)="ZZZ"+FNITOA$(NUMOFBLKLLBL)
5140 NUMOFBLKLLBL=NUMOFBLKLLBL+1
5150 RETURN
5160 '
5170 ' *** NEXT ***
5180 '
5190 IF BLKTYP$(BLOCKNEST)="FOR" THEN 5230
5200 IF BLKTYP$(BLOCKNEST)="FOR1" THEN 5370
5210 RETURN 'ERROR!
5220 ' [ type 2 ]
5230 LL$=BLKFLG$(BLOCKNEST)
5240 LL$=LL$+":GOTO *"+BLKLOOPL$(BLOCKNEST)
5250 LL$=LL$+":*"+BLKEXITL$(BLOCKNEST)
5260 LB$=""
5270 WHILE SEP$<>CHR$(13)
5280 GOSUB 3420
5290 LB$=LB$+TKN$
5300 IF SEP$<>CHR$(13) AND SEP$<>CHR$(34) THEN LB$=LB$+SEP$
5310 WEND
5320 IF L$="" THEN L$=LL$ ELSE L$=LL$+":"+L$
5330 SEP$=""
5340 BLOCKNEST=BLOCKNEST-1
5350 RETURN
5360 ' [ type 1 ]
5370 LB$=""
5380 WHILE SEP$<>CHR$(13)
5390 GOSUB 3420
5400 LB$=LB$+TKN$
5410 IF SEP$<>CHR$(13) AND SEP$<>CHR$(34) THEN LB$=LB$+SEP$
5420 WEND
5430 LB$="NEXT "+LB$+":*"+BLKEXITL$(BLOCKNEST)
5440 IF L$="" THEN L$=LB$ ELSE L$=LB$+":"+L$
5450 SEP$=""
5460 BLOCKNEST=BLOCKNEST-1
5470 RETURN
5480 '
5490 ' *** BREAK ***
5500 '
5510 IF BLOCKNEST=-1 THEN RETURN 'ERROR!
5520 FOR I=BLOCLNEST TO 0 STEP -1
5530 IF BLKTYP$(I)="FOR" OR BLKTYP$(I)="FOR1" THEN 5580
5540 IF BLKTYP$(I)="DO" OR BLKTYP$(I)="WHILE" THEN 5580
5550 NEXT
5560 RETURN '!ERROR
5570 '
5580 LM$="GOTO *"+BLKEXITL$(I)
5590 SEP$=""
5600 RETURN
5610 '
5620 ' *** block IF ***
5630 '
5640 LB$=""
5650 GOSUB 3420
5660 IF TKN$="THEN" THEN 5710
5670 LB$=LB$+TKN$
5680 IF SEP$<>CHR$(34) THEN LB$=LB$+SEP$
5690 GOTO 5650
5700 '
5710 IF ELSEIF=0 THEN BLOCKNEST=BLOCKNEST+1
5720 IF SEP$=CHR$(13) THEN BLKTYP$(BLOCKNEST)="IF":GOTO 5740 '[ type 2 ]
5730 BLKTYP$(BLOCKNEST)="IF1":SEP$="" '[ type 1 ]
5740 LL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
5750 NUMOFBLKLLBL=NUMOFBLKLLBL+1
5760 BLKLOOPL$(BLOCKNEST)=LL$
5770 IF ELSEIF=0 THEN BLKEXITL$(BLOCKNEST)=""
5780 LB$="IF ("+LB$+")=0 THEN *"+LL$
5790 IF L$="" THEN L$=LB$ ELSE L$=LB$+":"+L$
5800 SEP$=""
5810 RETURN
5820 '
5830 ' *** ELSE ***
5840 '
5850 IF LM$<>"" THEN GOSUB 3170
5860 IF BLKEXITL$(BLOCKNEST)="" THEN 5890
5870 LL$=BLKEXITL$(BLOCKNEST)
5880 GOTO 5920
5890 LL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
5900 NUMOFBLKLLBL=NUMOFBLKLLBL+1
5910 BLKEXITL$(BLOCKNEST)=LL$
5920 LM$="GOTO *"+LL$:GOSUB 3170
5930 LM$="*"+BLKLOOPL$(BLOCKNEST)
5940 SEP$=CHR$(13)
5950 RETURN
5960 '
5970 ' *** ENDIF ***
5980 '
5990 IF BLKEXITL$(BLOCKNEST)="" THEN LM$="*"+BLKLOOPL$(BLOCKNEST):GOTO 6010
6000 LM$="*"+BLKEXITL$(BLOCKNEST)
6010 BLOCKNEST=BLOCKNEST-1
6020 SEP$=CHR$(13)
6030 RETURN
6040 '
6050 ' *** ELSEIF ***
6060 '
6070 '[ ELSE ]
6080 GOSUB 5850 ' [ ELSE ]
6090 GOSUB 3170
6100 ' [ IF ]
6110 ELSEIF=1
6120 GOSUB 5640 '[ IF ]
6130 ELSEIF=0
6140 RETURN
6150 '
6160 ' *** WHILE ***
6170 '
6180 BLOCKNEST=BLOCKNEST+1
6190 BLKTYP$(BLOCKNEST)="WHILE"
6200 LL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
6210 NUMOFBLKLLBL=NUMOFBLKLLBL+1
6220 BLKEXITL$(BLOCKNEST)=LL$
6230 L$="WHILE "+L$:SEP$=""
6240 RETURN
6250 '
6260 ' *** WEND ***
6270 '
6280 LL$="WEND:*"+BLKEXITL$(BLOCKNEST)
6290 IF L$="" THEN L$=LL$ ELSE L$=LL$+":"+L$
6300 BLOCKNEST=BLOCKNEST-1
6310 SEP$=""
6320 RETURN
6330 '
6340 ' *** DO ***
6350 '
6360 BLOCKNEST=BLOCKNEST+1
6370 LL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
6380 NUMOFBLKLLBL=NUMOFBLKLLBL+1
6390 LM$="*"+LL$:SEP$=CHR$(13)
6400 BLKLOOPL$(BLOCKNEST)=LL$
6410 LL$="ZZZ"+FNITOA$(NUMOFBLKLLBL)
6420 NUMOFBLKLLBL=NUMOFBLKLLBL+1
6430 BLKEXITL$(BLOCKNEST)=LL$
6440 RETURN
6450 '
6460 ' *** LOOP ***
6470 '
6480 LL$="IF "
6490 GOSUB 3420
6500 LL$=LL$+TKN$
6510 IF SEP$=CHR$(13) THEN 6550
6520 IF SEP$<>CHR$(34) THEN LL$=LL$+SEP$
6530 GOTO 6490
6540 '
6550 LL$=LL$+" THEN *"+BLKLOOPL$(BLOCKNEST)
6560 LL$=LL$+":*"+BLKEXITL$(BLOCKNEST)
6570 IF L$="" THEN L$=LL$ ELSE L$=LL$+":"+L$
6580 SEP$=""
6590 BLOCKNEST=BLOCKNEST-1
6600 RETURN
6610 '
6620 ' *** LOCAL ***
6630 '
6640 IF L$="" THEN GOSUB 3250:GOSUB *TRIMLINE
6650 GOSUB 3420
6660 IF TKN$="LOCAL" THEN 6720
6670 IF SEP$=CHR$(34) THEN SEP$=""
6680 IF SEP$=CHR$(13) THEN IF L$="" THEN SEP$="" ELSE SEP$=":"
6690 L$=TKN$+SEP$+L$
6700 RETURN
6710 '
6720 GOSUB 3420
6730 IF TKN$="" THEN 6790
6740 TYP=INSTR("!#$%",SEP$)-1
6750 IF TYP>=0 THEN GOSUB 3420
6760 IF TYP=-1 THEN TYP=DEFAULTVARTYPE
6770 LVARGID$(TYP,NUMOFLVAR(TYP))=TKN$
6780 NUMOFLVAR(TYP)=NUMOFLVAR(TYP)+1
6790 IF SEP$<>CHR$(13) THEN 6720
6800 GOTO 6640
6810 '
6820 ' *** MAKESTACK ***
6830 '
6840 LM$="'[ STACK FRAME ]":GOSUB 3170
6850 FOR I=0 TO 2
6860 LL$=""
6870 GOSUB 3420
6880 LL$=LL$+TKN$
6890 IF SEP$="," THEN 6930
6900 IF SEP$<>CHR$(34) THEN LL$=LL$+SEP$
6910 GOTO 6870
6920 '
6930 LM$="DIM "+STACKID$+MID$("!#$",I+1,1)+"("+LL$+")":GOSUB 3170
6940 LM$=STACKPTR$+"("+FNITOA$(I)+")=0":GOSUB 3170
6950 NEXT
6960 '
6970 LL$=""
6980 GOSUB 3420
6990 LL$=LL$+TKN$
7000 IF SEP$=CHR$(13) THEN 7040
7010 IF SEP$<>CHR$(34) THEN LL$=LL$+SEP$
7020 GOTO 6980
7030 '
7040 LM$="DIM "+STACKID$+"%("+LL$+")":GOSUB 3170
7050 LM$=STACKPTR$+"(3)=0"
7060 RETURN
7070 '
7080 ' *** DEFSNG ***
7090 '
7100 DEFAULTVARTYPE=0
7110 GOTO 7260
7120 '
7130 ' *** DEFDBL ***
7140 '
7150 DEFAULTVARTYPE=1
7160 GOTO 7260
7170 '
7180 ' *** DEFSTR ***
7190 '
7200 DEFAULTVARTYPE=2
7210 GOTO 7260
7220 '
7230 ' *** DEFINT ***
7240 '
7250 DEFAULTVARTYPE=3
7260 WHILE SEP$<>CHR$(13)
7270 GOSUB 3420
7280 WEND
7290 RETURN
7300 '
7310 ' *** PASS 3 ***
7320 '
7330 *PASS3
7340 PRINT "PASS 3 --- Solve Sub-routine Calls"
7350 ON ERROR GOTO *KILLFILE
7360 OPEN OUTFILE$ FOR OUTPUT AS #1
7370 ON ERROR GOTO 0
7380 OPEN SOURCEFILE$ FOR INPUT AS #2
7390 LINENO=10:LINES=0
7400 LM$="' [ BPP PASS 3 ]":LR$="":GOSUB 7450
7410 GOSUB *SOLVESUB
7420 CLOSE #1:CLOSE #2
7430 PRINT USING "##### lines done.";LINES
7440 RETURN
7450 '
7460 ' *** Output a Line ***
7470 ' [input] LINENO : line number
7480 ' LM$ : content of the line
7490 ' LR$ : comment of the line
7500 '
7510 LN$=FNITOA$(LINENO)+" "
7520 LINENO=LINENO+10
7530 PRINT#1,LN$+LM$;
7540 IF LR$<>"" THEN PRINT#1,"'"+LR$;
7550 PRINT#1,""
7560 LM$="":LR$=""
7570 RETURN
7580 '
7590 ' *** Solve Relations of Sub-routines ***
7600 '
7610 *SOLVESUB
7620 WHILE EOF(2)=0
7630 GOSUB 3250 'get a line
7640 LL$=L$
7650 GOSUB 3420 'get a token
7660 IF TKN$="CALL" THEN GOSUB 7750:GOTO 7690
7670 LM$=LL$
7680 GOSUB 7450 'put a line with line number
7690 WEND
7700 RETURN
7710 '
7720 '
7730 ' *** CALL ***
7740 '
7750 GOSUB 3420
7760 SID$=TKN$
7770 GOSUB 7820 'set prameters
7780 LM$="GOSUB *"+SID$:GOSUB 7450
7790 GOSUB 8080 'get return value
7800 RETURN
7810 '
7820 IF NUMOFSUB=0 THEN 7860
7830 FOR I=0 TO NUMOFSUB-1
7840 IF SID$=SUBID$(I) THEN 7880
7850 NEXT
7860 SID=-1:PNUM=0:RETURN
7870 '
7880 SID=I:PNUM=SUBPC(I)
7890 BNEST=0
7900 IF PNUM=0 THEN RETURN
7910 FOR I=0 TO PNUM-1
7920 LL$=""
7930 GOSUB 3420
7940 LL$=LL$+TKN$
7950 IF SEP$="(" THEN BNEST=BNEST+1
7960 IF SEP$=")" THEN IF BNEST=0 THEN 8010 ELSE BNEST=BNEST-1
7970 IF SEP$="," OR SEP$=CHR$(13) THEN 8010
7980 IF SEP$<>CHR$(34) THEN LL$=LL$+SEP$
7990 GOTO 7930
8000 '
8010 TYP=SUBPTYP(SID,I) MOD 10:LID=SUBPARA(SID,I)
8020 PARA$(I)=LL$
8030 LM$=STACKID$+MID$("!#$%",TYP+1,1)+"("
8040 LM$=LM$+STACKPTR$+"("+FNITOA$(TYP)+")+"+FNITOA$(LID)+")="
8050 LM$=LM$+LL$:GOSUB 7450
8060 NEXT
8070 '
8080 FOR I=0 TO PNUM-1
8090 IF SUBPTYP(SID,I)<10 THEN 8150
8100 LM$=PARA$(I)+"="
8110 LM$=LM$+STACKID$+MID$("!#$%",(SUBPTYP(SID,I) MOD 10)+1,1)+"("
8120 LM$=LM$+STACKPTR$+"("+FNITOA$(SUBPTYP(SID,I) MOD 10)+")+"
8130 LM$=LM$+FNITOA$(SUBPARA(SID,I))+")"
8140 GOSUB 7450
8150 NEXT
8160 RETURN
8170 '
8180 ' *** Get a Token ***
8190 '
8200 ' [input] L$
8210 ' [output] TKN$ : extracted token
8220 ' SEP$ : separator
8230 ' L$ : one token deleted
8240 '
8250 *GETTOKEN
8260 IF LEFT$(L$,1)=CHR$(34) THEN 8480
8270 Z0=1
8280 WHILE Z0<=LEN(L$)
8290 Z0$=MID$(L$,Z0,1)
8300 IF Z0$=CHR$(34) THEN 8440
8310 Z1=1
8320 WHILE Z1<=LEN(SEPARATOR$)
8330 IF Z0$=MID$(SEPARATOR$,Z1,1) THEN 8410
8340 Z1=Z1+1
8350 WEND
8360 Z0=Z0+1
8370 WEND
8380 TKN$=L$:SEP$=CHR$(13):L$=""
8390 RETURN
8400 ' separator found
8410 IF Z0=1 THEN TKN$="":SEP$=LEFT$(L$,1):L$=MID$(L$,2):RETURN
8420 TKN$=LEFT$(L$,Z0-1):SEP$=MID$(L$,Z0,1):L$=MID$(L$,Z0+1)
8430 RETURN
8440 ' quautation found
8450 TKN$=LEFT$(L$,Z0-1):SEP$=" ":L$=MID$(L$,Z0)
8460 RETURN
8470 ' quauted string
8480 IF LEN(L$)=1 THEN L$=L$+CHR$(34)
8490 Z0=INSTR(MID$(L$,2),CHR$(34))
8500 IF Z0=0 THEN L$=L$+CHR$(34):Z0=LEN(L$)
8510 TKN$=LEFT$(L$,Z0+1):SEP$=CHR$(34)
8520 IF Z0+1=LEN(L$) THEN L$="" ELSE L$=MID$(L$,Z0+2)
8530 RETURN
8540 '
8550 ' *** Trimming a Line ***
8560 '
8570 ' [input] L$
8580 ' [output] L$
8590 '
8600 *TRIMLINE
8610 Z0=1:Z0$=L$:L$="":Z2$=""
8620 '
8630 IF Z0>LEN(Z0$) THEN RETURN
8640 Z1$=MID$(Z0$,Z0,1)
8650 IF Z1$=" " OR Z1$=CHR$(9) THEN Z0=Z0+1:GOTO 8630
8660 L$=L$+Z2$:Z2$=" "
8670 '
8680 IF Z0>LEN(Z0$) THEN RETURN
8690 Z1$=MID$(Z0$,Z0,1)
8700 IF Z1$="'" THEN RETURN
8710 IF Z1$=" " OR Z1$=CHR$(9) THEN 8630
8720 IF Z1$=CHR$(34) THEN 8750
8730 L$=L$+Z1$:Z0=Z0+1:GOTO 8680
8740 ' quautation found
8750 L$=L$+CHR$(34)
8760 Z0=Z0+1:IF Z0>LEN(Z0$) THEN L$=L$+CHR$(34):RETURN
8770 Z1=INSTR(MID$(Z0$,Z0),CHR$(34))
8780 IF Z1=0 THEN L$=L$+CHR$(34):RETURN
8790 L$=L$+MID$(Z0$,Z0,Z1)
8800 Z0=Z0+Z1:GOTO 8630
8810 '
8820 ' *** To Upper ***
8830 '
8840 ' [input] L$
8850 ' [output] L$
8860 '
8870 *TOUPPER
8880 Z0$=L$:L$="":Z1=0
8890 FOR Z0=1 TO KLEN(Z0$)
8900 Z1$=KMID$(Z0$,Z0,1)
8910 IF Z1$=CHR$(34) THEN Z1=1-Z1
8920 IF Z1 THEN 8940
8930 IF Z1$>="a" AND Z1$<="z" THEN Z1$=CHR$(ASC(Z1$)-32)
8940 L$=L$+Z1$
8950 NEXT
8960 RETURN
8970 '
8980 ' *** Output Token ***
8990 '
9000 ' [input] TKN$, SEP$
9010 '
9020 *OUTTOKEN
9030 IF SEP$=CHR$(13) THEN PRINT#1,TKN$ :RETURN
9040 IF SEP$=CHR$(34) THEN PRINT#1,TKN$;:RETURN
9050 PRINT TKN$;SEP$;
9060 RETURN